using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Json;
using System.Collections.Concurrent;
using System.Threading.Channels;
using WebRtcProject.Models.Configuration;

namespace WebRtcProject.Services.Logging
{
    public class HighPerformanceLogSink : ILogEventSink, IDisposable
    {
        private readonly Channel<LogEvent> _channel;
        private readonly ChannelWriter<LogEvent> _writer;
        private readonly ChannelReader<LogEvent> _reader;
        private readonly ITextFormatter _formatter;
        private readonly PerformanceOptions _performanceOptions;
        private readonly RateLimitOptions _rateLimitOptions;
        private readonly Task _processingTask;
        private readonly CancellationTokenSource _cancellationTokenSource;
        private readonly SemaphoreSlim _rateLimitSemaphore;
        private readonly Timer _rateLimitResetTimer;
        private volatile bool _disposed;

        // 性能计数器
        private long _totalLogEvents;
        private long _droppedLogEvents;
        private long _fastPathEvents;
        private readonly DateTime _startTime;

        public HighPerformanceLogSink(
            ITextFormatter formatter,
            PerformanceOptions performanceOptions,
            RateLimitOptions rateLimitOptions,
            int bufferSize = 10000)
        {
            _formatter = formatter ?? new JsonFormatter();
            _performanceOptions = performanceOptions;
            _rateLimitOptions = rateLimitOptions;
            _startTime = DateTime.UtcNow;
            _cancellationTokenSource = new CancellationTokenSource();

            // 创建高性能Channel
            var options = new BoundedChannelOptions(bufferSize)
            {
                FullMode = BoundedChannelFullMode.DropOldest, // 缓冲区满时丢弃旧数据
                SingleReader = false,
                SingleWriter = false,
                AllowSynchronousContinuations = false
            };

            _channel = Channel.CreateBounded<LogEvent>(options);
            _writer = _channel.Writer;
            _reader = _channel.Reader;

            // 初始化限流
            _rateLimitSemaphore = new SemaphoreSlim(_rateLimitOptions.BurstCapacity, _rateLimitOptions.BurstCapacity);
            _rateLimitResetTimer = new Timer(ResetRateLimit, null, 
                _rateLimitOptions.TimeWindow, _rateLimitOptions.TimeWindow);

            // 启动后台处理任务
            _processingTask = Task.Run(ProcessLogEventsAsync, _cancellationTokenSource.Token);
        }

        public void Emit(LogEvent logEvent)
        {
            if (_disposed) return;

            try
            {
                Interlocked.Increment(ref _totalLogEvents);

                // 应用限流策略
                if (_rateLimitOptions.Enabled && !TryAcquireRateLimit())
                {
                    Interlocked.Increment(ref _droppedLogEvents);
                    return;
                }

                // 检查是否为快速路径日志
                if (IsFastPathLog(logEvent))
                {
                    Interlocked.Increment(ref _fastPathEvents);
                    // 快速路径：直接处理，不经过队列
                    ProcessLogEventDirect(logEvent);
                    return;
                }

                // 应用采样策略
                if (_performanceOptions.Sampling.Enabled && !ShouldSampleLog(logEvent))
                {
                    return;
                }

                // 异步写入Channel
                if (!_writer.TryWrite(logEvent))
                {
                    Interlocked.Increment(ref _droppedLogEvents);
                }
            }
            catch (Exception ex)
            {
                // 避免日志系统本身的异常影响应用
                Console.WriteLine($"HighPerformanceLogSink error: {ex.Message}");
            }
        }

        private bool IsFastPathLog(LogEvent logEvent)
        {
            if (_performanceOptions.FastPathLevels.Contains(logEvent.Level.ToString()))
                return true;

            if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContext) && 
                sourceContext is ScalarValue scalarValue)
            {
                var context = scalarValue.Value?.ToString();
                return _performanceOptions.CriticalNamespaces.Any(ns => 
                    context?.StartsWith(ns, StringComparison.OrdinalIgnoreCase) == true);
            }

            return false;
        }

        private bool ShouldSampleLog(LogEvent logEvent)
        {
            // 错误和致命级别日志不参与采样
            if (_performanceOptions.Sampling.ExcludedLevels.Contains(logEvent.Level.ToString()))
                return true;

            // 简单的计数器采样
            return _totalLogEvents % _performanceOptions.Sampling.SampleRate == 0;
        }

        private bool TryAcquireRateLimit()
        {
            return _rateLimitSemaphore.Wait(0); // 非阻塞获取
        }

        private void ResetRateLimit(object? state)
        {
            try
            {
                var currentCount = _rateLimitSemaphore.CurrentCount;
                var releaseCount = Math.Min(
                    _rateLimitOptions.MaxLogEntriesPerSecond,
                    _rateLimitOptions.BurstCapacity - currentCount);

                if (releaseCount > 0)
                {
                    _rateLimitSemaphore.Release(releaseCount);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Rate limit reset error: {ex.Message}");
            }
        }

        private void ProcessLogEventDirect(LogEvent logEvent)
        {
            try
            {
                using var writer = new StringWriter();
                _formatter.Format(logEvent, writer);
                var formattedLog = writer.ToString();

                // 这里可以直接写入到快速存储或发送到监控系统
                Console.Write(formattedLog);

                // 如果是关键错误，也可以同时写入错误日志文件
                if (logEvent.Level >= LogEventLevel.Error)
                {
                    WriteToErrorLog(formattedLog);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Direct log processing error: {ex.Message}");
            }
        }

        private async Task ProcessLogEventsAsync()
        {
            try
            {
                await foreach (var logEvent in _reader.ReadAllAsync(_cancellationTokenSource.Token))
                {
                    try
                    {
                        await ProcessLogEventAsync(logEvent);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Log processing error: {ex.Message}");
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // 正常取消，忽略
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Log processing task error: {ex.Message}");
            }
        }

        private async Task ProcessLogEventAsync(LogEvent logEvent)
        {
            using var writer = new StringWriter();
            _formatter.Format(logEvent, writer);
            var formattedLog = writer.ToString();

            // 根据日志级别和源选择不同的处理策略
            if (IsStructuredLoggingEnabled(logEvent))
            {
                await WriteStructuredLogAsync(logEvent, formattedLog);
            }
            else
            {
                await WriteStandardLogAsync(formattedLog);
            }
        }

        private bool IsStructuredLoggingEnabled(LogEvent logEvent)
        {
            if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContext) && 
                sourceContext is ScalarValue scalarValue)
            {
                var context = scalarValue.Value?.ToString();
                return _performanceOptions.StructuredLoggingNamespaces.Any(ns => 
                    context?.StartsWith(ns, StringComparison.OrdinalIgnoreCase) == true);
            }
            return false;
        }

        private async Task WriteStructuredLogAsync(LogEvent logEvent, string formattedLog)
        {
            // 结构化日志处理：可以发送到ElasticSearch、Grafana等
            await WriteToStandardOutputAsync(formattedLog);
            
            // 可以在这里添加到其他sink，比如数据库、消息队列等
            if (logEvent.Level >= LogEventLevel.Warning)
            {
                await WriteToMonitoringSystemAsync(logEvent);
            }
        }

        private async Task WriteStandardLogAsync(string formattedLog)
        {
            await WriteToStandardOutputAsync(formattedLog);
        }

        private async Task WriteToStandardOutputAsync(string log)
        {
            await Console.Out.WriteAsync(log);
        }

        private async Task WriteToMonitoringSystemAsync(LogEvent logEvent)
        {
            // 这里可以集成到监控系统，比如发送到RabbitMQ、Redis等
            // 示例：发送警告和错误到监控队列
            await Task.Delay(1); // 占位符
        }

        private void WriteToErrorLog(string formattedLog)
        {
            try
            {
                var errorLogPath = Path.Combine("logs", "errors", $"error-{DateTime.Now:yyyy-MM-dd}.log");
                Directory.CreateDirectory(Path.GetDirectoryName(errorLogPath)!);
                File.AppendAllText(errorLogPath, formattedLog);
            }
            catch
            {
                // 忽略错误日志写入失败
            }
        }

        public LoggingStatistics GetStatistics()
        {
            var uptime = DateTime.UtcNow - _startTime;
            return new LoggingStatistics
            {
                TotalLogEvents = Interlocked.Read(ref _totalLogEvents),
                DroppedLogEvents = Interlocked.Read(ref _droppedLogEvents),
                FastPathEvents = Interlocked.Read(ref _fastPathEvents),
                Uptime = uptime,
                EventsPerSecond = uptime.TotalSeconds > 0 ? _totalLogEvents / uptime.TotalSeconds : 0,
                DropRate = _totalLogEvents > 0 ? (double)_droppedLogEvents / _totalLogEvents * 100 : 0
            };
        }

        public void Dispose()
        {
            if (_disposed) return;
            _disposed = true;

            try
            {
                _writer.Complete();
                _cancellationTokenSource.Cancel();
                _processingTask?.Wait(TimeSpan.FromSeconds(5));
                _rateLimitResetTimer?.Dispose();
                _rateLimitSemaphore?.Dispose();
                _cancellationTokenSource?.Dispose();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Dispose error: {ex.Message}");
            }
        }
    }

    public class LoggingStatistics
    {
        public long TotalLogEvents { get; set; }
        public long DroppedLogEvents { get; set; }
        public long FastPathEvents { get; set; }
        public TimeSpan Uptime { get; set; }
        public double EventsPerSecond { get; set; }
        public double DropRate { get; set; }
    }
} 